<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>es5 对象的原型链</title>
  <!-- 
  在 JavaScript ES5 中，原型链是实现对象继承和属性共享的核心机制。
  1. 原型的基本概念
  - 每个 JavaScript 对象都有一个内部属性  `[[Prototype]]` ，指向另一个对象，这个对象称为原型。
  - 原型可以通过  `Object.getPrototypeOf(obj)`  或  `obj.__proto__`  访问。

  2. 原型链的形成
  - 当你访问一个对象的属性或方法时，JavaScript 引擎会首先查找该对象自身的属性。如果没有找到，它会查找对象的原型，接着是原型的原型，直到找到属性或达到原型链的末尾（通常是  `null` ）。
  function Parent() {
      this.parentProperty = "I am a parent property";
  }

  Parent.prototype.parentMethod = function() {
      console.log("This is a method from Parent");
  };

  function Child() {
      this.childProperty = "I am a child property";
  }

  // Child 的原型指向 Parent 的实例
  Child.prototype = new Parent();
  Child.prototype.constructor = Child;

  var childInstance = new Child();
  console.log(childInstance.childProperty); // 输出: I am a child property
  console.log(childInstance.parentProperty); // 输出: I am a parent property
  childInstance.parentMethod(); // 输出: This is a method from Parent
  在这个例子中， `childInstance`  通过原型链访问了  `Parent`  的属性和方法。

  3. 原型链的特点
  - 共享性：通过原型链，多个实例可以共享同一个方法，从而节省内存。例如，所有  `Child`  的实例都可以访问  `Parent.prototype`  上定义的方法。
  - 动态性：如果在原型上添加或修改属性和方法，所有通过该原型创建的实例都会受到影响。

  4. 原型链的查找过程
  当你访问一个对象的属性时，JavaScript 的查找过程如下：
    1. 检查对象自身是否有该属性。
    2. 如果没有，检查对象的原型。
    3. 如果原型上也没有，继续查找原型的原型，直到找到属性或达到原型链的末尾。

  5. 原型链的限制
  - 性能问题：过长的原型链可能导致性能问题，因为查找属性需要逐层查找。
  - 属性遮蔽：如果实例对象有与原型同名的属性，实例对象会优先使用自己的属性，这被称为“遮蔽”。
  childInstance.parentProperty = "I am a child property now";
  console.log(childInstance.parentProperty); // 输出: I am a child property now
  console.log(childInstance.__proto__.parentProperty); // 输出: I am a parent property
  6. 总结
  原型链是 JavaScript 中实现继承和共享属性的重要机制。通过理解原型链的工作原理，开发者可以更好地构建对象模型，实现代码复用和继承。掌握原型链的特点和限制，对于编写高效和可维护的 JavaScript 代码至关重要。
   -->
</head>
<body>

  <script>
    // 1. {} 对象的原型
    var info = {}
    // 相当于
    var info = new Object()
    console.log(info.__proto__ === Object.prototype) // true;

    // 2. 原型链
    const obj = {
      name: 'scope chain',
      age: 18
    }

    // 原型链查找顺序
    // 1.obj上面查找
    // 2.obj.__proto__上面查找
    // 3.obj.__proto__.__proto__ -> null 上面查找(undefined)
    // console.log(obj.message)

    // 3. 原型链的修改
    obj.__proto__ = {
      message: 'hello __proto__'
    }

    obj.__proto__.__proto__ = {
      message: 'hello __proto__ __proto__'
    }

    obj.__proto__.__proto__.__proto__ = {
      message: 'hello __proto__ __proto__'
    }
    
    console.log(obj.message) // hello __proto__;
    

  </script>
  
</body>
</html>